package sdk.pay;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import okhttp3.Call;
import okhttp3.Response;
import sdk.pay.constant.PayConfigure;
import sdk.pay.constant.PayConstant;
import sdk.pay.constant.PayExceptionType;
import sdk.pay.listener.PayGetPayStatusListener;
import sdk.pay.listener.PayGetPayTypeListener;
import sdk.pay.listener.PayUtilCallBack;
import sdk.pay.model.PayParam;
import sdk.pay.model.PayTypeModel;
import sdk.pay.model.TokenParam;
import sdk.pay.utils.PayDESUtil;
import sdk.pay.utils.PayExceptionUtil;
import sdk.pay.utils.PayLogUtil;
import sdk.pay.utils.PayMD5Util;
import sdk.pay.utils.PayNetUtil;
import sdk.pay.utils.PayPackageUtil;
import sdk.pay.utils.PayTimeUtil;
import sdk.pay.utils.PayToastUtil;

public final class PayHelperIml extends PayHelper {

    public PayHelperIml(Activity activity, String appid, String key, String vector, String systemName,
                        String code, PayUtilCallBack callback, boolean payStatusCallBack) {
        super(activity, callback, payStatusCallBack);
        PayLogUtil.logBase("version code = " + PayConstant.VERSION_CODE);
        PayExceptionUtil.getInstance().init(activity.getApplicationContext());

        mHandlerThread = new HandlerThread(PayHelperIml.class.getSimpleName());
        mHandlerThread.start();
        mPayHandler = new PayHandler(mHandlerThread.getLooper());
        if (TextUtils.isEmpty(appid) || TextUtils.isEmpty(key) || TextUtils.isEmpty(vector)
                || TextUtils.isEmpty(systemName)) {
            return;
        }
        setPayParam(appid, key, vector, systemName.toLowerCase(), code);
    }

    @Override
    protected void doGetServices(int type) {
        PayLogUtil.logFifth("doGetServices start");
        clearPayUrl();
        Date date = new Date();
        DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String key = PayMD5Util.getMD5(dateFormat.format(date));
        JSONObject object = new JSONObject();
        try {
            object.put("SysFlag", mPayInfo.getPaySystemId().toUpperCase());
        } catch (JSONException e) {
            e.printStackTrace();
            PayLogUtil.logFourth("doGetServices JSONException = " + e.getMessage());
            showToast(PayExceptionType.DATA_EXCEPTION.getMessage());
            PayExceptionUtil.getInstance().saveExceptionFile("doGetServices JSONException = " + e.getMessage());
        }
        String encode = PayDESUtil.encode("wolegequ" + key, object.toString());
        String plainParam = String.format("info=%s", encode);
        String signParam = String.format("&nonce=%s", key);
        String url = getServicesDefaultUrl(mPayInfo.getPaySystemId()) + "?" + plainParam + signParam;
        PayLogUtil.logBase("GetServices url = " + url);
        getServices(type, url);
    }

    private String getServicesDefaultUrl(String systemName) {
        systemName = systemName.toLowerCase();
        return systemName.equals("jft") ?
                PayConstant.GET_SERVICES_JFT : systemName.equals("yhb") ?
                PayConstant.GET_SERVICES_YHB : systemName.equals("yzf") ?
                PayConstant.GET_SERVICES_YZF : systemName.equals("wsf") ?
                PayConstant.GET_SERVICES_WSF : null;

    }

    @Override
    protected void getServices(final int type, String url) {
        mPayTimeUtil.setTimeData(null, PayTimeUtil.TIMER_TYPE_SERVICE);
        getCall(getServices, url, new PayCallback() {
            @Override
            public void onFailure() {
                mPayTimeUtil.setTimeData("getServices Failure", PayTimeUtil.TIMER_TYPE_SERVICE);
                getServicesFailure(type);
            }

            @Override
            public void onSuccess(Call call, Response response) throws IOException {
                String result = "";
                try {
                    if (null != response.body()) {
                        result = response.body().string();
                        PayLogUtil.logBase("getServices onResponse result = " + result);
                        if (response.isSuccessful()) {
                            JSONObject jsonObject = new JSONObject(result);
                            String flag = jsonObject.getString("flag");
                            if (flag.equals(TASK_SUCCESS)) {
                                PayLogUtil.logFifth("getServices onResponse Success");
                                String nonce = jsonObject.getString("nonce");
                                String msg = jsonObject.getString("msg");
                                SharedPreferences.Editor editor = mSharedPreferences.edit();
                                editor.putString(PayConstant.SHAREPERFERENCE_MSG_KEY, msg);
                                editor.putString(PayConstant.SHAREPERFERENCE_NONCE_KEY, nonce);
                                editor.apply();
                                mPayTimeUtil.setTimeData("", PayTimeUtil.TIMER_TYPE_SERVICE);
                                getServicesFinal(type);
                            } else {
                                PayLogUtil.logThird("getServices onResponse result = " + jsonObject.toString());
                                mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_SERVICE);
                                getServicesFailure(type);
                            }
                        } else {
                            mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_SERVICE);
                            getServicesFailure(type);
                        }
                    } else {
                        mPayTimeUtil.setTimeData("getServices response body null", PayTimeUtil.TIMER_TYPE_SERVICE);
                        getServicesFailure(type);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    PayLogUtil.logFourth("getServices onResponse Exception = " + e.getMessage());
                    if (result.length() < 1) {
                        result = "getServices onResponse Exception = " + e.getMessage();
                    }
                    mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_SERVICE);
                    getServicesFailure(type);
                    PayExceptionUtil.getInstance().saveExceptionFile("getServices onResponse Exception = " + e.getMessage());
                }
            }
        });
    }

    @Override
    protected void getServicesFailure(int type) {
        PayConfigure.setAPIs(PayConfigure.DEFAULT_PAY_URL);
        getServicesFinal(type);
        doErrorUpload();
    }

    private void getServicesFinal(int type) {
        switch (type) {
            case DO_GET_PAY_TOKEN:
                sendMessage(DO_GET_PAY_TOKEN, 1);
                break;
            case DO_GET_PAY_TYPE:
                sendMessage(DO_GET_PAY_TYPE, 1);
                break;
            case DO_STEP_PAY:
                sendMessage(DO_STEP_PAY, 1);
                break;
        }
    }

    @Override
    protected void getToken() {
        if (PayNetUtil.isNetworkAvailable(mActivity)) {
            mPayHandler.sendEmptyMessage(DO_GET_PAY_TOKEN);
        } else {
            PayLogUtil.logFifth("getToken network not available");
            showToast(PayExceptionType.NET_WORK_NOT_AVAILABLE.getMessage());
        }
    }

    public void getToken(TokenParam tokenParam, PayGetPayTypeListener getPayTypeListener) {
        if (tokenParam == null) {
            PayLogUtil.logFirst("getToken tokenParam is null");
            showToast(PayExceptionType.DATA_EXCEPTION.getMessage());
            return;
        }
        mTokenParam = tokenParam;
        mGetPayTypeListener = getPayTypeListener;
        getToken();
    }

    public void pay(TokenParam tokenParam, int payType) {
        if (tokenParam == null) {
            PayLogUtil.logFirst("getToken tokenParam is null");
            showToast(PayExceptionType.DATA_EXCEPTION.getMessage());
            return;
        }
        mPayInfo.setPayTypeId(payType);
        mTokenParam = tokenParam;
        stepPay();
    }

    @Override
    public void getToken(TokenParam tokenParam, int payType) {
        pay(tokenParam, payType);
    }

    private void stepPay() {
        if (PayNetUtil.isNetworkAvailable(mActivity)) {
            mPayHandler.sendEmptyMessage(DO_STEP_PAY);
        } else {
            PayLogUtil.logFifth("getToken network not available");
            showToast(PayExceptionType.NET_WORK_NOT_AVAILABLE.getMessage());
        }
    }

    @Override
    protected void doGetToken(boolean isFresh) {
        PayLogUtil.logSecond("doGetToken flag = " + isFresh);
        if (configServices("doGetToken", isFresh, DO_GET_PAY_TOKEN)) {
            doGetTokenParams();
            mPayTimeStatisticsUtil.doUploadIfNeeded();
        }
    }

    @Override
    protected void doStep(boolean isFresh) {
        PayLogUtil.logSecond("doStep flag = " + isFresh);
        if (configServices("doStep", isFresh, DO_STEP_PAY)) {
            doStepParams();
            mPayTimeStatisticsUtil.doUploadIfNeeded();
        }
    }

    private boolean configServices(String doTag, boolean isFresh, int type) {
        PayLogUtil.logBase("configServices");
        String paySdkMsg = mSharedPreferences.getString(PayConstant.SHAREPERFERENCE_MSG_KEY, null);
        String paySdkNonce = mSharedPreferences.getString(PayConstant.SHAREPERFERENCE_NONCE_KEY, null);
        boolean isSync = true;
        JSONArray servers = null;
        String nextSync = null;
        try {
            if (!TextUtils.isEmpty(paySdkMsg)) {
                String decode = PayDESUtil.decode("wolegequ" + paySdkNonce, paySdkMsg);
                if (!TextUtils.isEmpty(decode)) {
                    if (isJson(decode)) {
                        JSONObject msgObject = new JSONObject(decode);
                        PayLogUtil.logFirst(" msgObject = " + msgObject.toString());
                        nextSync = msgObject.getString("nextSync");
                        servers = msgObject.getJSONArray("servers");
                        String name = msgObject.getString("name");
                        if (!name.toUpperCase().equals(mPayInfo.getPaySystemId().toUpperCase())) {
                            nextSync = null;
                            servers = null;
                            clearPayUrl();
                        }
                    } else {
                        nextSync = null;
                        servers = null;
                        clearPayUrl();
                    }
                } else {
                    nextSync = null;
                    servers = null;
                    clearPayUrl();
                    if (isFresh) {
                        showToast(PayExceptionType.RETURN_ERROR_DATA.getMessage());
                        return false;
                    }
                }
            }
            if (isFresh) {
                if (servers != null && !TextUtils.isEmpty(nextSync)) {
                    PayLogUtil.logFirst(doTag + " servers = " + servers);
                    SharedPreferences.Editor editor = mSharedPreferences.edit();
                    editor.putInt(PayConstant.SHAREPERFERENCE_SERVCERS_SUM_KEY, servers.length());
                    int current = mSharedPreferences.getInt(PayConstant.SHAREPERFERENCE_SERVCERS_CURRENT_KEY, 0);
                    PayConfigure.setAPIs((String) servers.get(current));
                    editor.putInt(PayConstant.SHAREPERFERENCE_SERVCERS_CURRENT_KEY, current);
                    editor.apply();
                    return true;
                } else {
                    PayLogUtil.logFifth(doTag + " servers = null");
                    return true;
                }
            } else {
                if (!TextUtils.isEmpty(nextSync)) {
                    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    long syncTime = dateFormat.parse(nextSync).getTime();
                    long nowTime = new Date().getTime();
                    isSync = nowTime >= syncTime;
                }
                if (isSync) {
                    doGetServices(type);
                    return false;
                } else {
                    if (TextUtils.isEmpty((String) servers.get(0))) {
                        doGetServices(type);
                        return false;
                    } else if (TextUtils.isEmpty(PayConfigure.PAY_URL)) {
                        SharedPreferences.Editor editor = mSharedPreferences.edit();
                        editor.putInt(PayConstant.SHAREPERFERENCE_SERVCERS_SUM_KEY, servers.length());
                        int current = mSharedPreferences.getInt(PayConstant.SHAREPERFERENCE_SERVCERS_CURRENT_KEY, 0);
                        PayConfigure.setAPIs((String) servers.get(current));
                        editor.putInt(PayConstant.SHAREPERFERENCE_SERVCERS_CURRENT_KEY, current);
                        editor.apply();
                    }
                    return true;
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
            PayLogUtil.logFourth(doTag + " JSONParse failure = " + e.getMessage());
            showToast(PayExceptionType.DATA_EXCEPTION.getMessage());
            PayExceptionUtil.getInstance().saveExceptionFile(doTag + " JSONParse failure = " + e.getMessage());
        } catch (ParseException e) {
            e.printStackTrace();
            PayLogUtil.logFourth(doTag + " syncParse failure = " + e.getMessage());
            showToast(PayExceptionType.DATA_EXCEPTION.getMessage());
            PayExceptionUtil.getInstance().saveExceptionFile(doTag + " syncParse failure = " + e.getMessage());
        }
        return false;
    }

    @Override
    protected void doGetTokenParams() {
        String params = doTokenOrStepParams(false);
        getToken(params);
    }

    private void doStepParams() {
        String params = doTokenOrStepParams(true);
        stepPay(params);
    }

    private String doTokenOrStepParams(boolean isStep) {
        PayLogUtil.logFifth("doTokenOrStepParams start ");

        if (!checkTokenParams()) {
            throw new RuntimeException((isStep ? "Step" : "Get Token") + " Params is error!");
        }
        mPayTimeStatisticsUtil.getTimeStatisticsModel().setOrderNumber(mTokenParam.getP2_order());
        mPayTimeStatisticsUtil.getTimeStatisticsModel().setUserCode(mTokenParam.getP1_usercode());
        mPayTimeStatisticsUtil.getTimeStatisticsModel().setPlatform(mPayInfo.getPaySystemId());
        String plainParam = "?appid=" + mPayInfo.getAppId() + "&info=";
        JSONObject object = composeTokenJson(isStep);
        if (object == null) {
            return null;
        }
        PayLogUtil.logSecond((isStep ? "Step" : "Get Token") + " object = " + object.toString());
        String info = object.toString().replace("\\/", "/");
        String paramInfo = encryptAES(isStep ? stepPay : getToken, info);
        if (TextUtils.isEmpty(paramInfo)) {
            return null;
        }
        return plainParam + paramInfo;
    }

    @Override
    protected void getToken(String params) {
        mPayTimeUtil.setTimeData(null, PayTimeUtil.TIMER_TYPE_TOKEN);
        String url = PayConfigure.PAY_GET_TOKEN + params;
        mPayTimeStatisticsUtil.getTimeStatisticsModel().setTokenUrl(url);
        PayLogUtil.logBase("getToken url = " + url);
        getCall(getToken, url, new PayCallback() {
            @Override
            public void onFailure() {
                mPayTimeUtil.setTimeData("getToken Failure", PayTimeUtil.TIMER_TYPE_TOKEN);
                showToast(PayExceptionType.GET_TOKEN_FAILURE.getMessage());
                setNextApi();
            }

            @Override
            public void onSuccess(Call call, Response response) throws IOException {
                if (null != response.body()) {
                    String result = response.body().string();
                    PayLogUtil.logBase("getToken onResponse result = " + result);
                    if (response.isSuccessful()) {
                        try {
                            JSONObject objectResult = new JSONObject(result);
                            String flag = objectResult.getString("flag");
                            if (flag.equals(TASK_SUCCESS)) {
                                final String tokenMsg = decryptAES(getToken, objectResult.getString("msg"));
                                if (TextUtils.isEmpty(tokenMsg)) {
                                    mPayTimeUtil.setTimeData("getToken onResponse msg isEmpty", PayTimeUtil.TIMER_TYPE_TOKEN);
                                    return;
                                }
                                if (isJson(tokenMsg)) {
                                    JSONObject object = new JSONObject(tokenMsg);
                                    setToken(object.getString("token"));
                                    PayLogUtil.logFifth("getToken onResponse onPayDataResult");
                                    mPayTimeUtil.setTimeData("", PayTimeUtil.TIMER_TYPE_TOKEN);
                                    getPayTypes();
                                } else {
                                    showToast(PayExceptionType.DEFAULT_ERROR.getMessage());
                                    mActivity.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            PayToastUtil.showMessage(mActivity, tokenMsg);
                                        }
                                    });
                                    mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_TOKEN);
                                    doErrorUpload();
                                }
                            } else {
                                PayLogUtil.logThird("getToken onResponse failure flag = " + flag);
                                final String msg = objectResult.getString("msg");
                                if (msg.contains("非法交易")) {
                                    showToast(PayExceptionType.DEFAULT_ERROR.getMessage());
                                    mActivity.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            PayToastUtil.showMessage(mActivity, msg);
                                        }
                                    });
                                } else {
                                    showToast(PayExceptionType.GET_TOKEN_FAILURE.getMessage());
                                }
                                mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_TOKEN);
                                doErrorUpload();
                            }
                        } catch (Exception e) {
                            PayLogUtil.logFourth("getToken onResponse exception = " + e.getMessage());
                            showToast(PayExceptionType.RETURN_ERROR_DATA.getMessage());
                            mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_TOKEN);
                            setNextApi();
                            PayExceptionUtil.getInstance().saveExceptionFile("getToken onResponse exception = " + e.getMessage());
                        }
                    } else {
                        mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_TOKEN);
                        showToast(PayExceptionType.SERVER_CONNECTION_EXCEPTION.getMessage());
                        setNextApi();
                    }
                } else {
                    mPayTimeUtil.setTimeData("getToken response body null", PayTimeUtil.TIMER_TYPE_TOKEN);
                    showToast(PayExceptionType.SERVER_CONNECTION_EXCEPTION.getMessage());
                    setNextApi();
                }
            }
        });
    }

    @Override
    protected void stepPay(String params) {
        if (!checkPayTypes(mPayInfo.getPayTypeId())) {
            return;
        }
        mPayTimeUtil.setTimeData(null, PayTimeUtil.TIMER_TYPE_PAYURL);
        String url = PayConfigure.STEP_PAY + params;
        PayLogUtil.logBase("stepPay url = " + url);
        mPayInfo.resetPayParam();
        getCall(stepPay, url, new PayCallback() {

            @Override
            public void onFailure() {
                showToast(PayExceptionType.STEP_PAY_FAILURE.getMessage());
                mPayTimeUtil.setTimeData("stepPay Failure", PayTimeUtil.TIMER_TYPE_PAYURL);
                setNextApi();
            }

            @Override
            public void onSuccess(Call call, Response response) throws IOException {
                if (null != response.body()) {
                    String result = response.body().string();
                    PayLogUtil.logBase("stepPay onResponse result = " + result);
                    if (response.isSuccessful()) {
                        try {
                            JSONObject objectResult = new JSONObject(result);
                            String flag = objectResult.getString("flag");
                            if (flag.equals(TASK_SUCCESS)) {
                                final String stepMsg = decryptAES(stepPay, objectResult.getString("msg"));
                                if (TextUtils.isEmpty(stepMsg)) {
                                    mPayTimeUtil.setTimeData("stepPay onResponse stepMsg isEmpty", PayTimeUtil.TIMER_TYPE_PAYURL);
                                    return;
                                }
                                if (isJson(stepMsg)) {
                                    JSONObject object = new JSONObject(stepMsg);
                                    JSONArray jsonArray = object.getJSONArray("paramlist");
                                    PayLogUtil.logBase(" stepPay array = " + jsonArray.toString());
                                    setPayParams(jsonArray);
                                    setToken(object.getString("token"));
                                    mPayTimeUtil.setTimeData("", PayTimeUtil.TIMER_TYPE_PAYURL);
                                    pay();
                                } else {
                                    showToast(PayExceptionType.DEFAULT_ERROR.getMessage());
                                    mActivity.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            PayToastUtil.showMessage(mActivity, stepMsg);
                                        }
                                    });
                                    mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_PAYURL);
                                    doErrorUpload();
                                }
                            } else {
                                PayLogUtil.logThird("stepPay onResponse failure flag = " + flag);
                                final String msg = objectResult.getString("msg");
                                if (msg.contains("非法交易")) {
                                    showToast(PayExceptionType.DEFAULT_ERROR.getMessage());
                                    mActivity.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            PayToastUtil.showMessage(mActivity, msg);
                                        }
                                    });
                                } else {
                                    showToast(PayExceptionType.STEP_PAY_FAILURE.getMessage());
                                }
                                mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_PAYURL);
                                doErrorUpload();
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_PAYURL);
                            PayLogUtil.logFourth("stepPay exception = " + e.getMessage());
                            showToast(PayExceptionType.RETURN_ERROR_DATA.getMessage());
                            setNextApi();
                            PayExceptionUtil.getInstance().saveExceptionFile("stepPay exception = " + e.getMessage());
                        }
                    } else {
                        mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_PAYURL);
                        showToast(PayExceptionType.SERVER_CONNECTION_EXCEPTION.getMessage());
                        setNextApi();
                    }
                } else {
                    mPayTimeUtil.setTimeData("stepPay response body null", PayTimeUtil.TIMER_TYPE_PAYURL);
                    showToast(PayExceptionType.SERVER_CONNECTION_EXCEPTION.getMessage());
                    setNextApi();
                }
            }
        });
    }

    private boolean checkTokenParams() {
        return mTokenParam != null && checkParams(mTokenParam.getP1_usercode(), mTokenParam.getP2_order(), mTokenParam.getP3_money(),
                mTokenParam.getP4_returnurl(), mTokenParam.getP5_notifyurl(), mTokenParam.getP6_ordertime(),
                mTokenParam.getP9_paymethod(), mTokenParam.getP7_sign());
    }

    private JSONObject composeTokenJson(boolean isStep) {
        try {
            JSONObject object = mTokenParam.getTokenParams();
            object.put("ext_sdkversion", PayConstant.VERSION_CODE);
            String mType = Build.MODEL;
            int sdkInt = Build.VERSION.SDK_INT;
            String release = Build.VERSION.RELEASE;
            String manufacturer = Build.MANUFACTURER;
            PackageManager packageManager = mActivity.getPackageManager();
            boolean hasPermission = packageManager.PERMISSION_GRANTED ==
                    packageManager.checkPermission("android.permission.READ_PHONE_STATE", mActivity.getPackageName());
            String number = "";
            if (hasPermission) {
                TelephonyManager tm = (TelephonyManager) mActivity.getSystemService(Context.TELEPHONY_SERVICE);
                String serialNumber = tm.getSimSerialNumber();
                if (!TextUtils.isEmpty(serialNumber)) {
                    number = tm.getLine1Number();
                }
            }
            object.put("ext_device", String.format("MODEL=%s SDK=%d RELEASE=%s FAC=%s TELEPHONE=%s",
                    mType, sdkInt, release, manufacturer, number));
            object.put("packagename", mActivity.getPackageName());
            if (isStep) {
                object.put("ext_paytype", mPayInfo.getPayTypeId());
            }
            return object;
        } catch (JSONException e) {
            PayLogUtil.logFourth("composeTokenJson JSONException = " + e.getMessage());
            showToast(PayExceptionType.DATA_EXCEPTION.getMessage());
            e.printStackTrace();
            PayExceptionUtil.getInstance().saveExceptionFile("composeTokenJson JSONException = " + e.getMessage());
            return null;
        }
    }

    @Override
    protected void setNextApi() {
        PayLogUtil.logFifth("setNextApi start");
        doErrorUpload();
        int sum = mSharedPreferences.getInt(PayConstant.SHAREPERFERENCE_SERVCERS_SUM_KEY, 0);
        int current = mSharedPreferences.getInt(PayConstant.SHAREPERFERENCE_SERVCERS_CURRENT_KEY, 0);
        if (current >= sum - 1) {
            clearPayUrl();
        } else {
            String paySdkMsg = mSharedPreferences.getString(PayConstant.SHAREPERFERENCE_MSG_KEY, null);
            String paySdkNonce = mSharedPreferences.getString(PayConstant.SHAREPERFERENCE_NONCE_KEY, null);
            JSONArray servers;
            try {
                if (!TextUtils.isEmpty(paySdkMsg)) {
                    String decode = PayDESUtil.decode("wolegequ" + paySdkNonce, paySdkMsg);
                    if (!TextUtils.isEmpty(decode)) {
                        if (isJson(decode)) {
                            JSONObject msgObject = new JSONObject(decode);
                            PayLogUtil.logSecond("setNextApi msgObject = " + msgObject.toString());
                            servers = msgObject.getJSONArray("servers");
                            PayConfigure.setAPIs((String) servers.get(++current));
                            SharedPreferences.Editor edit = mSharedPreferences.edit();
                            edit.putInt(PayConstant.SHAREPERFERENCE_SERVCERS_CURRENT_KEY, current);
                            edit.apply();
                        } else {
                            clearPayUrl();
                        }
                    } else {
                        clearPayUrl();
                    }
                }
            } catch (JSONException e) {
                PayLogUtil.logFourth("setNextApi JSONException = " + e.getMessage());
                e.printStackTrace();
                PayExceptionUtil.getInstance().saveExceptionFile("setNextApi JSONException = " + e.getMessage());
            }
        }
    }

    @Override
    protected void doGetPayType(boolean isFresh) {
        if (!configServices("doGetPayType", isFresh, DO_GET_PAY_TYPE)) {
            return;
        }

        PayLogUtil.logFifth("doGetPayType start");
        String plainParam = "?appid=" + mPayInfo.getAppId() + "&info=";
        JSONObject object = new JSONObject();
        try {
            object.put("usercode", mPayInfo.getCode());
            object.put("devicetype", "3");
            object.put("packagename", mActivity.getPackageName());
        } catch (JSONException e) {
            PayLogUtil.logFourth("doGetPayType JSONException = " + e.getMessage());
            showToast(PayExceptionType.DATA_EXCEPTION.getMessage());
            e.printStackTrace();
            PayExceptionUtil.getInstance().saveExceptionFile("doGetPayType JSONException = " + e.getMessage());
            return;
        }
        PayLogUtil.logFourth("doGetPayType JSONObject = " + object.toString());
        String info = object.toString();
        String paramInfo = encryptAES(getPayTypes, info);
        String url = PayConfigure.PAY_URL_TYPE + plainParam + paramInfo;
        PayLogUtil.logBase("GetPayType url = " + url);
        getPayTypes(url);
    }

    @Override
    public void getPayTypes(PayGetPayTypeListener getPayTypeListener) {
        mGetPayTypeListener = getPayTypeListener;
        getPayTypes();
    }

    public void getPayTypes() {
        mPayHandler.sendEmptyMessage(DO_GET_PAY_TYPE);
    }

    private void setToken(String token) {
        mPayInfo.setToken(token);
    }

    public void setPayParam(String... payParam) {
        boolean validInitParams = checkInitParams(payParam);
        if (!validInitParams) {
            return;
        }
        setValidInitParams(validInitParams);
        mPayInfo.setPayParam(payParam);
        String systemName = mPayInfo.getPaySystemId();
        PayLogUtil.logSecond("setPayParam systemName = " + systemName);
        PayConfigure.DEFAULT_PAY_URL = getSystemDefaultUrl(systemName);
    }

    private String getSystemDefaultUrl(String systemName) {
        systemName = systemName.toLowerCase();
        return systemName.equals("jft") ?
                PayConstant.DEFAULT_PAY_URL_JFT : systemName.equals("yhb") ?
                PayConstant.DEFAULT_PAY_URL_YHB : systemName.equals("yzf") ?
                PayConstant.DEFAULT_PAY_URL_YZF : systemName.equals("wsf") ?
                PayConstant.DEFAULT_PAY_URL_WSF : null;
    }

    @Override
    public List<PayTypeModel> getPayTypeModels() {
        return mPayInfo.getPayTypeModels();
    }

    @Override
    protected void getPayTypes(String url) {
        mPayTimeUtil.setTimeData(null, PayTimeUtil.TIMER_TYPE_PAYLIST);
        getCall(getPayTypes, url, new PayCallback() {
            @Override
            public void onFailure() {
                showToast(PayExceptionType.GET_PAY_METHOD_FAILED.getMessage());
                mPayTimeUtil.setTimeData("getPayTypes Failure", PayTimeUtil.TIMER_TYPE_PAYLIST);
                doErrorUpload();
            }

            @Override
            public void onSuccess(Call call, Response response) throws IOException {
                if (null != response.body()) {
                    String result = response.body().string();
                    PayLogUtil.logBase("getPayTypes onResponse result = " + result);
                    if (response.isSuccessful()) {
                        try {
                            JSONObject jsonObject = new JSONObject(result);
                            if (jsonObject.getString("flag").equals(TASK_SUCCESS)) {
                                ArrayList<PayTypeModel> payTypeModels = new ArrayList<>();
                                final String msg = decryptAES(getPayTypes, jsonObject.getString("msg"));
                                if (TextUtils.isEmpty(msg)) {
                                    mPayTimeUtil.setTimeData("getPayTypes onResponse msg isEmpty", PayTimeUtil.TIMER_TYPE_PAYLIST);
                                    return;
                                }
                                PayLogUtil.logBase("getPayTypes decrypt info = " + msg);
                                if (isJsonArray(msg)) {
                                    JSONArray jsonArray = new JSONArray(msg);
                                    for (int i = 0; i < jsonArray.length(); i++) {
                                        JSONObject jsonObjectitem = jsonArray.getJSONObject(i);
                                        int typeId = 0;
                                        try {
                                            typeId = Integer.parseInt(jsonObjectitem.getString("typeid"));
                                        } catch (NumberFormatException e) {
                                            e.printStackTrace();
                                            PayLogUtil.logFourth("getPayTypes onResponse NumberFormatException = " + e.getMessage());
                                            PayExceptionUtil.getInstance().saveExceptionFile("getPayTypes onResponse NumberFormatException = " + e.getMessage());
                                        }
                                        String isPilotRun = jsonObjectitem.getString("IsPilotRun");
                                        payTypeModels.add(new PayTypeModel(jsonObjectitem.getString("typename"),
                                                typeId, jsonObjectitem.getString("remark")));
                                        if (typeId == TYPE_ALIPAY
                                                && isPilotRun.equals("1")) {
                                            mPayInfo.setIsPilotRun(true);
                                            getPayParam(typeId);
                                        }
                                    }
                                    mPayInfo.setPayTypeModels(payTypeModels);
                                    mPayTimeUtil.setTimeData("", PayTimeUtil.TIMER_TYPE_PAYLIST);
                                    if (mPayInfo.getIsPilotRun()) {
                                        sendEmptyMessageDelayed(DO_SHOW_PAY_TYPE, 2000L);
                                    } else {
                                        sendEmptyMessage(DO_SHOW_PAY_TYPE);
                                    }
                                    PayLogUtil.logSecond("getPayTypes onResponse mIsPilotRun = " +
                                            mPayInfo.getIsPilotRun());
                                } else {
                                    showToast(PayExceptionType.DEFAULT_ERROR.getMessage());
                                    mActivity.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            PayToastUtil.showMessage(mActivity, msg);
                                        }
                                    });
                                    mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_PAYLIST);
                                    doErrorUpload();
                                }
                            } else {
                                PayLogUtil.logThird("getPayTypes onResponse response = " + jsonObject.toString());
                                final String msg = jsonObject.getString("msg");
                                if (msg.contains("非法交易")) {
                                    showToast(PayExceptionType.DEFAULT_ERROR.getMessage());
                                    mActivity.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            PayToastUtil.showMessage(mActivity, msg);
                                        }
                                    });
                                } else {
                                    showToast(PayExceptionType.GET_PAY_METHOD_FAILED.getMessage());
                                }
                                mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_PAYLIST);
                                doErrorUpload();
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            PayLogUtil.logFourth("getPayTypes onResponse exception = " + e.getMessage());
                            showToast(PayExceptionType.RETURN_ERROR_DATA.getMessage());
                            mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_PAYLIST);
                            doErrorUpload();
                            PayExceptionUtil.getInstance().saveExceptionFile("getPayTypes onResponse exception = " + e.getMessage());
                        }
                    } else {
                        showToast(PayExceptionType.SERVER_CONNECTION_EXCEPTION.getMessage());
                        mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_PAYLIST);
                        doErrorUpload();
                    }
                } else {
                    showToast(PayExceptionType.SERVER_CONNECTION_EXCEPTION.getMessage());
                    mPayTimeUtil.setTimeData("getPayTypes response body null", PayTimeUtil.TIMER_TYPE_PAYLIST);
                    doErrorUpload();
                }
            }
        });
    }

    @Override
    protected void doGetParams() {
        PayLogUtil.logFifth("doGetParams start");
        boolean secondPay = false;
        String token = mPayInfo.getToken();
        if (TextUtils.isEmpty(token)) {
            throw new RuntimeException("token is null ,getParams must be getToken before");
        }
        int payTypeId = mPayInfo.getPayTypeId();
        String plainParam = "?appid=" + mPayInfo.getAppId() + "&info=";
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("token", token);
            jsonObject.put("paytypeid", String.valueOf(payTypeId));
            jsonObject.put("packagename", mActivity.getPackageName());
        } catch (JSONException e) {
            PayLogUtil.logFourth("doGetParams jsonexception = " + e.getMessage());
            showToast(PayExceptionType.DATA_EXCEPTION.getMessage());
            e.printStackTrace();
            PayExceptionUtil.getInstance().saveExceptionFile("doGetParams jsonexception = " + e.getMessage());
            return;
        }
        PayLogUtil.logSecond("doGetParams jsonObject = " + jsonObject.toString());
        String info = jsonObject.toString();
        String paramInfo = encryptAES(getPayParams, info);
        String url = PayConfigure.PAY_URL_PAY + plainParam + paramInfo;
        mPayInfo.resetPayParam();
        String key = token + payTypeId;
        if (mArrayMap.containsKey(key)) {
            PayParam value = mArrayMap.get(key);
            mPayInfo.setImgUrl(value.getImgUrl());
            mPayInfo.setOpenUrl(value.getOpenUrl());
            mPayInfo.setAliImgId(value.getAliImgId());
            mPayInfo.setPayToken(value.getPayToken());
            mPayInfo.setWXAppId(value.getWXAppId());
            mPayInfo.setSdkFlag(value.getSdkFlag());
            mPayInfo.setPayJson(value.getPayJson());
            mPayInfo.setPlugin(value.getPlugin());
            PayLogUtil.logSecond("doGetParams hash value = " + value.toString());
            secondPay = true;
        }
        PayLogUtil.logSecond("doGetParams secondPay = " + secondPay);
        getPayParam(url, secondPay);
    }

    @Override
    protected void getPayParam(String url, boolean secondPay) {
        if (secondPay) {
            pay();
            return;
        }
        mPayTimeUtil.setTimeData(null, PayTimeUtil.TIMER_TYPE_PAYURL);
        PayLogUtil.logBase("doGetParams url = " + url);
        getCall(getPayParams, url, new PayCallback() {
            @Override
            public void onFailure() {
                showToast(PayExceptionType.GET_PAY_PARAM_FAILED.getMessage());
                mPayTimeUtil.setTimeData("getPayParam Failure", PayTimeUtil.TIMER_TYPE_PAYURL);
                doErrorUpload();
            }

            @Override
            public void onSuccess(Call call, Response response) throws IOException {
                if (null != response.body()) {
                    String result = response.body().string();
                    PayLogUtil.logBase("getPayParam onResponse result = " + result);
                    if (response.isSuccessful()) {
                        try {
                            JSONObject jsonObject = new JSONObject(result);
                            if (jsonObject.getString("flag").equals(TASK_SUCCESS)) {
                                final String paramInfo = decryptAES(getPayParams, jsonObject.getString("msg"));
                                if (TextUtils.isEmpty(paramInfo)) {
                                    mPayTimeUtil.setTimeData("getPayParam onResponse msg isEmpty", PayTimeUtil.TIMER_TYPE_PAYURL);
                                    return;
                                }
                                if (isJson(paramInfo)) {
                                    JSONObject object = new JSONObject(paramInfo);
                                    JSONArray jsonArray = object.getJSONArray("paramlist");
                                    PayLogUtil.logBase("getPayParam array = " + jsonArray.toString());
                                    setPayParams(jsonArray);
                                    String token = mPayInfo.getToken();
                                    int type = mPayInfo.getPayTypeId();
                                    mArrayMap.put(token + type, new PayParam(mPayInfo.getAliImgId(),
                                            mPayInfo.getImgUrl(), mPayInfo.getOpenUrl(), mPayInfo.getWXAppId(),
                                            mPayInfo.getPayToken(), mPayInfo.getSdkFlag(),
                                            mPayInfo.getPayJson(), mPayInfo.getPlugin()));
                                    mPayTimeUtil.setTimeData("", PayTimeUtil.TIMER_TYPE_PAYURL);
                                    pay();
                                } else {
                                    showToast(PayExceptionType.DEFAULT_ERROR.getMessage());
                                    mActivity.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            PayToastUtil.showMessage(mActivity, paramInfo);
                                        }
                                    });
                                    mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_PAYURL);
                                    doErrorUpload();
                                }
                            } else {
                                PayLogUtil.logThird("getPayParams onResponse result = " + result);
                                final String msg = jsonObject.getString("msg");
                                if (msg.contains("非法交易")) {
                                    showToast(PayExceptionType.DEFAULT_ERROR.getMessage());
                                    mActivity.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            PayToastUtil.showMessage(mActivity, msg);
                                        }
                                    });
                                } else {
                                    showToast(PayExceptionType.GET_PAY_PARAM_FAILED.getMessage());
                                }
                                mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_PAYURL);
                                doErrorUpload();
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            PayLogUtil.logFourth("getPayParams onResponse exception = " + e.getMessage());
                            showToast(PayExceptionType.RETURN_ERROR_DATA.getMessage());
                            mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_PAYURL);
                            doErrorUpload();
                            PayExceptionUtil.getInstance().saveExceptionFile("getPayParams onResponse exception = " + e.getMessage());
                        }
                    } else {
                        showToast(PayExceptionType.SERVER_CONNECTION_EXCEPTION.getMessage());
                        mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_PAYURL);
                        doErrorUpload();
                    }
                } else {
                    showToast(PayExceptionType.SERVER_CONNECTION_EXCEPTION.getMessage());
                    mPayTimeUtil.setTimeData("getPayParam response body null", PayTimeUtil.TIMER_TYPE_PAYURL);
                    doErrorUpload();
                }
            }
        });
    }

    private void setPayParams(JSONArray jsonArray) throws JSONException {
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject jsonObjectItem = jsonArray.getJSONObject(i);
            String paramCode = jsonObjectItem.getString("paramcode");
            String paramValue = jsonObjectItem.getString("paramvalue");
            switch (paramCode) {
                case "img":
                    mPayInfo.setImgUrl(paramValue);
                    break;
                case "imgid":
                    mPayInfo.setAliImgId(paramValue);
                    break;
                case "isopen":
                    mPayInfo.setOpenUrl(paramValue);
                    break;
                case "sdkflag":
                    mPayInfo.setSdkFlag(paramValue);
                    break;
                case "payToken":
                    mPayInfo.setPayToken(paramValue);
                    break;
                case "wxappid":
                    mPayInfo.setWXAppId(paramValue);
                    break;
                case "json":
                    mPayInfo.setPayJson(paramValue);
                    break;
                case "aliurl":
                    mPayInfo.setAliUrl(paramValue);
                    break;
                case "plugin":
                    mPayInfo.setPlugin(paramValue);
                    break;
                default:
                    break;
            }
        }
    }

    public void getPayParam(int typeId) {
        mPayInfo.setPayTypeId(typeId);
        if (checkPayTypes(typeId)) {
            sendEmptyMessage(DO_GET_PAY_PARAM);
        }
    }

    private boolean checkPayTypes(int typeId) {
        if (typeId == TYPE_WECHAT && !PayPackageUtil.isWeChatAvailable(mActivity)) {
            PayLogUtil.logFifth("getPayParam Find Not WeChat");
            showToast(PayExceptionType.WECHAT_NOT_AVAILABLE.getMessage());
            return false;
        }
        if (typeId == TYPE_ALIPAY && !PayPackageUtil.isAlipayAvailable(mActivity)) {
            if (mPayInfo.getIsPilotRun()) {
                mPayInfo.setIsPilotRun(false);
            } else {
                PayLogUtil.logFifth("getPayParam Find Not AliPay");
                showToast(PayExceptionType.ALIPAY_NOT_AVAILABLE.getMessage());
            }
            return false;
        }
        if (typeId == TYPE_QQPAY && !PayPackageUtil.isQQpayAvailable(mActivity)) {
            PayLogUtil.logFifth("getPayParam Find Not QQPay");
            showToast(PayExceptionType.QQPAY_NOT_AVAILABLE.getMessage());
            return false;
        }
        return true;
    }

    private void pay() {
        sendEmptyMessage(DO_PAY);
    }

    private void junPayDo() {
        PayExcessiveActivity.startActivityForResult(mActivity,
                mPayInfo, mCallBack, mPayStatusCallBack);
    }

    public void getPayStatus(PayGetPayStatusListener getPayStatusListener) {
        mGetPayStatusListener = getPayStatusListener;
        sendEmptyMessageDelayed(DO_GET_PAY_STATUS, 3000);
    }

    private void doPayStatus() {
        if (getPaying() && mPayStatusCallBack) {
            PayLogUtil.logFifth("doPayStatus start");
            if (TextUtils.isEmpty(mPayInfo.getToken())) {
                return;
            }
            String url = PayConfigure.ORDER_QUERY + "?token=" + mPayInfo.getToken();
            PayLogUtil.logBase("doPayStatus url = " + url);
            getPayStatus(url);
        }
    }

    @Override
    protected void getPayStatus(String url) {
        mPayTimeUtil.setTimeData(null, PayTimeUtil.TIMER_TYPE_CALLBACK);
        getCall(getPayStatus, url, new PayCallback() {
            @Override
            public void onFailure() {
                showToast(PayExceptionType.GET_PAY_STATUS_FAILED.getMessage());
                mPayTimeUtil.setTimeData("getPayStatus Failure", PayTimeUtil.TIMER_TYPE_CALLBACK);
                doErrorUpload();
            }

            @Override
            public void onSuccess(Call call, Response response) throws IOException {
                if (null != response.body()) {
                    String result = response.body().string();
                    PayLogUtil.logBase("getPayStatus onResponse result = " + result);
                    if (response.isSuccessful()) {
                        try {
                            JSONObject jsonObject = new JSONObject(result);
                            if (jsonObject.getString("flag").equals("success")) {
                                String payStatus = jsonObject.getString("msg");
                                showStatus(Integer.parseInt(payStatus));
                                if (payStatus.equals("1")) {
                                    PayLogUtil.logFifth("getPayStatus onResponse success");
                                } else {
                                    PayLogUtil.logFifth("getPayStatus onResponse failure");
                                }
                                mPayTimeUtil.setTimeData("", PayTimeUtil.TIMER_TYPE_CALLBACK);
                                mPayTimeStatisticsUtil.updateData();
                            } else {
                                PayLogUtil.logThird("getPayStatus onResponse failure response = " + jsonObject.toString());
                                showToast(PayExceptionType.GET_PAY_STATUS_FAILED.getMessage());
                                mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_CALLBACK);
                                doErrorUpload();
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            PayLogUtil.logFourth("getPayStatus onResponse failure with error = " + e.getMessage());
                            showToast(PayExceptionType.RETURN_ERROR_DATA.getMessage());
                            mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_CALLBACK);
                            doErrorUpload();
                            PayExceptionUtil.getInstance().saveExceptionFile("getPayStatus onResponse failure with error = " + e.getMessage());
                        }
                    } else {
                        showToast(PayExceptionType.SERVER_CONNECTION_EXCEPTION.getMessage());
                        mPayTimeUtil.setTimeData(result, PayTimeUtil.TIMER_TYPE_CALLBACK);
                        doErrorUpload();
                    }
                } else {
                    showToast(PayExceptionType.SERVER_CONNECTION_EXCEPTION.getMessage());
                    mPayTimeUtil.setTimeData("getPayStatus response body null", PayTimeUtil.TIMER_TYPE_CALLBACK);
                    doErrorUpload();
                }
            }
        });
    }

    private class PayHandler extends Handler {
        PayHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            int what = msg.what;
            switch (what) {
                case DO_GET_PAY_TYPE:
                    doGetPayType(msg.arg1 == 1);
                    break;
                case DO_GET_PAY_PARAM:
                    doGetParams();
                    break;
                case DO_PAY:
                    junPayDo();
                    break;
                case DO_SHOW_PAY_TYPE:
                    showPayTypeList();
                    break;
                case DO_GET_PAY_TOKEN:
                    doGetToken(msg.arg1 == 1);
                    break;
                case DO_GET_PAY_STATUS:
                    doPayStatus();
                    break;
                case DO_STEP_PAY:
                    doStep(msg.arg1 == 1);
                    break;
                default:
                    break;
            }
        }
    }

    private void doErrorUpload() {
        mPayTimeStatisticsUtil.doErrorUpload();
    }

}